
#include "BasicModule.h"
#include "Task.h"
#include "ConnectionControl.h"
#include "ConnectionFactory.h"
#include "RequestGet.h"
#include "../client-common/Device.h"
#include "../client-common/VersionTag.h"

using namespace Client::Common;

class CTaskSyncDevice : public CTask {

	VersionTagRef mVersionTag;
	string mSourceDevice;

	bool SyncFromServer(ConnectionRef conn) {

		if(!conn->IsControlConnection()) return false;
		ConnectionControlRef control_conn = boost::dynamic_pointer_cast<CConnectionControl, CConnection>(conn);

		RequestRef request(new CRequestCheck(string("devices")));
		ResponseRef response = control_conn->SendRequest(request);
		if(!response || response->GetStatus() != RESPONSE_STATUS_OK) return false;

		string content;
		response->GetContentAsString(content);
	
		TableRef td = Client::Common::CDevice::GetSerializedTable(content);
		if(td && td->GetCount() > 0) {
			boost::shared_array<RecordRef> recs = td->NextRecords(td->GetCount());
			int count = td->GetCurrentRecordsCount();
		
			for(int i = 0; i < count; i++) {
				DeviceRef dev = boost::dynamic_pointer_cast<Client::Common::CDevice, CRecord>(recs[i]);
				Client::Common::CDevice::AddDevice(dev);
			}
		}

		control_conn->AddCheckedVersionTag(mVersionTag);
		return true;
	}

	bool SyncFromDevice(ConnectionRef conn) {
		boost::shared_ptr<CConnectionControl> control_conn;
		ConnectionRef c;

		if(conn->IsControlConnection()) {
			control_conn = boost::dynamic_pointer_cast<CConnectionControl, CConnection>(conn);
	
			c = CConnectionFactory::CreateByPeer(mSourceDevice, control_conn, false);
			if(!c) {
				Engine::DebugStream << "CTaskSyncFile::Exec() - " << "Create connection failed\n";
				return false;
			}

			try {
				c->Setup();
			}
			catch(std::exception&) {
				return false;
			}
		}
		else {
			c = conn;
		}

		RequestRef request = RequestRef(new CRequestGet());
		request->AddParameter(string("target"), string("devices"));
		ResponseRef response = c->SendRequest(request);
		if(!response || response->GetStatus() != RESPONSE_STATUS_OK) return false;

		string content;
		response->GetContentAsString(content);
		if(content.length() == 0) return true;

		TableRef td = Client::Common::CDevice::GetSerializedTable(content);
		if(td->GetCount() == 0) return true;

		boost::shared_array<RecordRef> recs = td->NextRecords(td->GetCount());
		int count = td->GetCurrentRecordsCount();
		for(int i = 0; i < count; i++) {
			DeviceRef dev = boost::dynamic_pointer_cast<Client::Common::CDevice, CRecord>(recs[i]);
			Client::Common::CDevice::AddDevice(dev);
		}

		return true;
	}

public :

	CTaskSyncDevice(string& dev) : CTask(true), mSourceDevice(dev) { }
	CTaskSyncDevice(VersionTagRef vt) : CTask(false), mSourceDevice(vt->mDevice), mVersionTag(vt) { }

	virtual bool Exec(ConnectionRef conn) {
		if(mVersionTag) return SyncFromServer(conn);
		else return SyncFromDevice(conn);
	}
};

class CTaskSyncDeviceCreator : public CTaskCreator {

public :

	virtual TaskRef Create(VersionTagRef vt) {
		return TaskRef(new CTaskSyncDevice(vt));
	}

	virtual TaskRef CreateFullyTask(string& dev) {
		return TaskRef(new CTaskSyncDevice(dev));
	}
};

static CTaskSyncDeviceCreator sTaskSyncDeviceCreator;

void CBasicModule::InitTaskCreator()
{
	CTaskFactory::RegisterCreator(string("name"), &sTaskSyncDeviceCreator);
}
